/*
 *  Copyright 2013 Utkin Dmitry
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#ifndef PROTOQTRPC_RPCSERVERSESSION_H
#define PROTOQTRPC_RPCSERVERSESSION_H

#include <QObject>
#include <google/protobuf/message.h>
#include <google/protobuf/service.h>

namespace protoqtrpc
{
class RpcServer;
class RpcMessage;

/**
 * @brief Abstract peer information
 */
struct PeerInfo
{
};

class RpcServerSessionPrivate;

/**
 * @brief Base class for server sessions
 */
class RpcServerSession: public QObject
{
    Q_OBJECT

protected:
    /**
     * @brief Constructs RpcServerSession
     * @param server Pointer to server
     */
    RpcServerSession(RpcServer* server);

    /**
     * @brief Destroys RpcServerSession
     */
    virtual ~RpcServerSession();

    /**
     * @brief Gets peer info
     * @return peer info
     */
    virtual const PeerInfo& peerInfo() = 0;

protected slots:
    /**
     * @brief This slot is emmited when new message is received and parsed
     * @param msg Message received
     * @param peerInfo - client connection info
     */
    void handleMessage(const protoqtrpc::RpcMessage& msg);

signals:
    /**
     * @brief Sends message to client
     * @param msg Message to send
     */
    void sendMessage(const protoqtrpc::RpcMessage& msg);

    /**
     * @brief new client connected
     * @param peerInfo - client connection info
     */
    void connected(const protoqtrpc::PeerInfo& peerInfo);

    /**
     * @brief client disconnected
     * @param peerInfo - client connection info
     */
    void disconnected(const protoqtrpc::PeerInfo& peerInfo);

private:
    struct ActiveRequest;

    /**
     * @brief handle request from client
     * @param msg Message from client
     */
    void handleRequest(const RpcMessage& msg);

    /**
     * @brief Starts message cancelling
     * @param msg Cancellation msg
     */
    void handleCancel(const RpcMessage& msg);

    /**
     * @brief Finishes the request handling and sends the response to client
     * @param req Active request
     */
    void sendResponse(ActiveRequest* req);

private:
    Q_DECLARE_PRIVATE(RpcServerSession)
    Q_DISABLE_COPY(RpcServerSession)
    RpcServerSessionPrivate* d_ptr;
};

}

#endif
